package org.six11.olive3.picturephone;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.six11.olive3.client.OliveDrawingSurface;
import org.six11.olive3.client.OliveState;
import org.six11.olive3.net.Message;
import org.six11.olive3.net.MessageNames;
import org.six11.olive3.net.OliveNetworkTransmitter;
import org.six11.olive3.picturephone.server.PPMessageNames;
import org.six11.olive3.util.MiscFunctions;
import org.six11.olive3.util.MultiState;
import org.six11.util2.Debug;
import org.six11.util2.layout.FrontEnd;
import org.six11.util2.lev.NamedAction;

import static org.six11.util2.layout.FrontEnd.*;

/**
 * 
 * 
 * @author Gabe Johnson <johnsogg@cmu.edu>
 * 
 */
public class PicturephoneDrawingPane extends JPanel {

  private OliveDrawingSurface olive;
  private JTextArea descriptionText;
  private String descID;
  private OliveState oliveState;
  private MultiState programState;
  private PicturephoneControlBox controlBox;
  private List<NamedAction> actions;

  private static String DESC_LABEL = "description label";
  private static String DESC_TEXT = "description text";
  private static String DRAW_LABEL = "draw label";
  private static String DRAW = "draw";
  private static String CONTROLS = "control box";

  public PicturephoneDrawingPane(final OliveNetworkTransmitter xmit, final MultiState state) {
    this.programState = state;
    this.actions = new ArrayList<NamedAction>();
    oliveState = new OliveState(state);
    oliveState.addChangeListener(OliveState.EMPTY, new ChangeListener() {
      public void stateChanged(ChangeEvent e) {
        tweakActions();
      }
    });
    olive = new OliveDrawingSurface(xmit, oliveState);
    olive.setPreferredSize(new Dimension(400, 400));
    olive.setMaximumSize(new Dimension(400, 400));
    addComponentListener(new ComponentAdapter() {

      public void componentHidden(ComponentEvent e) {
        tweakActions();
      }
      public void componentShown(ComponentEvent e) {
        tweakActions();
      }
      
    });
    NamedAction doneAction = new NamedAction("Done") {
      public void activate() {
        if (descID != null) {
          Message m = new Message(PPMessageNames.MSG_SKETCH_DONE);
          m.addParam(MessageNames.PARAM_USER_ID, state.getString(MessageNames.PARAM_USER_ID));
          m.addParam(PPMessageNames.PARAM_DESC_ID, descID);
          xmit.addBodilessMessage(m);
          resetTemporaryState();
          bug("-> Sketched description " + descID);
        }
      }

      public synchronized void tweakState() {
        setEnabled(oliveState.hasData());
      }
    };
    actions.add(doneAction);

    NamedAction skipAction = new NamedAction("Skip") {
      public void activate() {
        String oldDescID = descID;
        resetTemporaryState();
        bug("-> Skipped description " + oldDescID);
      }

      public synchronized void tweakState() {
        setEnabled(!oliveState.hasData());
      }

    };
    actions.add(skipAction);
    controlBox = new PicturephoneControlBox(skipAction, doneAction, programState);

    FrontEnd fe = new FrontEnd();

    descriptionText = new JTextArea();
    descriptionText.setLineWrap(true);
    descriptionText.setWrapStyleWord(true);
    JScrollPane descriptionTextScroller = new JScrollPane(descriptionText,
        ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
        ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    fe.add(new JLabel("Description:"), DESC_LABEL);
    fe.add(descriptionTextScroller, DESC_TEXT);
    fe.add(new JLabel("Draw:"), DRAW_LABEL);
    fe.add(olive, DRAW);
    fe.add(controlBox, CONTROLS);

    fe.addRule(ROOT, N, DESC_LABEL, N, 12);
    fe.addRule(ROOT, W, DESC_LABEL, W, 12);

    fe.addRule(ROOT, W, DESC_TEXT, W);
    fe.addRule(DESC_LABEL, S, DESC_TEXT, N, 12);
    fe.addRule(ROOT, S, DESC_TEXT, S);
    fe.addRule(DRAW, W, DESC_TEXT, E, 12);

    fe.addRule(DRAW, W, DRAW_LABEL, W, 12);
    fe.addRule(DRAW, N, DRAW_LABEL, S, 12);

    fe.addRule(ROOT, E, DRAW, E);
    fe.addRule(ROOT, S, DRAW, S);

    fe.addRule(ROOT, N, CONTROLS, N);
    fe.addRule(ROOT, E, CONTROLS, E);

    setLayout(new BorderLayout());
    add(fe, BorderLayout.CENTER);
    tweakActions();
  }
  
  protected void tweakActions() {
    
    for (NamedAction a : actions) {
      a.tweak();
    }
  }

  protected void resetTemporaryState() {
    descID = null;
    descriptionText.setText("");
    oliveState.clearSurface();
    programState.whackValue(PicturephoneUI.DONE);
  }

  public void setDescription(String d, String id) {
    bug("* Sketching based on description " + id);
    descriptionText.setText(""); // clear
    descriptionText.append(MiscFunctions.unescape(d));
    descID = id;
  }

  private void bug(String what) {
    Debug.out("PicturephoneDrawingPane", what);
  }
}
